package org.raymond.iworks.study.basic.thread.phaser;

import lombok.extern.slf4j.Slf4j;

import java.util.Random;
import java.util.concurrent.Phaser;
import java.util.concurrent.TimeUnit;

@Slf4j
public class Demo2 {
    public static void main(String[] args) {
        test1();
    }

    // 模拟CyclicBarrier
    public static void test1(){
        Phaser phaser = new Phaser(){
            // 每个阶段结束后回调
            @Override
            protected boolean onAdvance(int phase, int registeredParties) {
                log.info("phase:{}, registeredParties:{}", phase, registeredParties);
                return super.onAdvance(phase, registeredParties);
            }
        };

        Bus bus1=new Bus(phaser,"小张");
        Bus bus2=new Bus(phaser,"小李");
        Bus bus3=new Bus(phaser,"小王");

        bus1.start();
        bus2.start();
        bus3.start();

        log.info("{}", phaser.getRegisteredParties());
    }

    static class Bus extends Thread {
        private Phaser phaser;
        private Random random;

        public Bus(Phaser phaser,String name){
            this.phaser=phaser;
            setName(name);
            random=new Random();
            phaser.register();
        }

        private void trip(int sleepRange,String cityName){
            log.info(this.getName()+" 准备去"+cityName+"....");
            int sleep=random.nextInt(sleepRange);
            try {
                TimeUnit.SECONDS.sleep(sleep);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            log.info(this.getName()+" 到达"+cityName+"...... ");
            if(this.getName().equals("小王1")){ //  测试掉队的情况
                try {
                    TimeUnit.SECONDS.sleep(7);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                phaser.arriveAndDeregister();
            }else {
                phaser.arriveAndAwaitAdvance();
            }
        }

        public void run() {
            try {
                int s=random.nextInt(3);
                TimeUnit.SECONDS.sleep(s);
                log.info(this.getName()+"  准备好了，旅行路线=北京=>上海=>杭州 ");
                phaser.arriveAndAwaitAdvance();// 等待所有的汽车准备好
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            trip(5,"北京");
            trip(5,"上海");
            trip(3,"杭州");
        }
    }
    public static void test2(){
        Phaser phaser = new Phaser(){
            @Override
            protected boolean onAdvance(int phase, int registeredParties) {
                log.info("结束了. phase:{}, registeredParties:{}", phase, registeredParties);
                return super.onAdvance(phase, registeredParties);
            }
        };

        Thread t1 = new Thread(()->{
            try {
                log.info("到达栅栏1");
                Thread.sleep(500);
                // 在所有parties都到达之前当前线程处于挂起等待状态,当所有parties都已到达之后线程被唤醒并且Phaser年龄增加,
                // 未到达parties数还原,Phaser复用
                phaser.arriveAndAwaitAdvance();
                log.info("突破栅栏1 1次");
                Thread.sleep(800);
                log.info("突破栅栏1 2次");
                phaser.arriveAndAwaitAdvance();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread t2 = new Thread(()->{
            try {
                log.info("到达栅栏2");
                Thread.sleep(1000);
                phaser.arriveAndAwaitAdvance();
                log.info("突破栅栏2 1次");
                Thread.sleep(1600);
                log.info("突破栅栏2 2次");
                phaser.arriveAndAwaitAdvance();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        phaser.register();
        t1.start();

        phaser.register();
        t2.start();
    }

}
